#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
提供web服务
"""

__author__ = 'Lei Chen'

import time

import demjson
from flask import Flask, request
from jinja2 import Environment, PackageLoader
from api import config, ApiManager
from dubbo import dubbo_invoke
from utils import *

app = Flask(__name__)
env = Environment(loader=PackageLoader('web'))
# 安装日志
setup_logging()

DIR = os.path.split(os.path.realpath(__file__))[0]
configParser = config.ApiConfigParser()
apiManager = ApiManager(configParser)

yamlParser = YamlParser()


# 首页
@app.route('/', methods=['GET'])
def index():
    titles = ['项目名称', '项目标识', '操作']
    datas = []
    try:
        for project in configParser.projects():
            name = project.get('name')
            symbol = project.get('symbol')
            yaml_dir = project.get('yaml_dir')
            datas.append([name, symbol,
                          '<a href="/project?dir={0}&system={1}">打开</a>'.format(yaml_dir, symbol)])
    except Exception as err:
        return error(err)

    return tmpl(titles=titles, datas=datas)


# 项目首页
@app.route('/project', methods=['GET'])
def project():
    try:
        system = request.args['system']
        dir = request.args['dir']
    except KeyError as err:
        logging.error(err)
        return error(err)

    titles = ['标题', '路径', '类型', '操作', '格式校验']

    datas = []
    try:
        for yaml in yamlParser.list(dir):
            title = yaml.get('title')
            path = yaml.get('path')
            type = yaml.get('type')
            is_dir = yaml.get('is_dir')
            if is_dir:
                datas.append([title, path, '目录',
                              '【<a href="/project?dir={0}&system={1}">打开</a>】'.format(path, system),
                              '<span style="color: green">success</span>'])
            else:
                content = yamlParser.valid(path)
                if len(content) == 0:
                    datas.append([title, path, type,
                                  '【<a href="/list?name={path}">查看</a>】【<a href="/yaml?name={path}">测试</a>】'.format(
                                      path=path),
                                  '<span style="color: green">success</span>'])
                else:
                    datas.append([title, path, type,
                                  '查看'.format(title),
                                  '测试'.format(path),
                                  '<span style="color: red">{0}</span>'.format('</br>'.join(content))])

    except Exception as err:
        return error(err)

    return tmpl(titles=titles, datas=datas)


# 显示测试用例列表
@app.route('/list', methods=['GET'])
def list():
    try:
        name = request.args['name']
    except KeyError as err:
        logging.error(err)
        return error(err)
    yaml = yamlParser.get(name)
    testes = yaml.get('test')
    titles = ['ID', '分组', '用例名称', '地址', '方法', '消息头', '参数', '测试']
    datas = [
        [test.get('id'), test.get('group'), test.get('name'), test.get('server'), test.get('method'),
         demjson.encode(test.get('headers')),
         demjson.encode(test.get('params')), '<a href="/yaml?id={0}&name={1}">测试</a>'.format(test.get('id'), name)] for
        test
        in testes]
    return tmpl(titles=titles, datas=datas)


# 显示测试报告
@app.route('/yaml', methods=['GET'])
def yaml():
    try:
        name = request.args['name']
    except KeyError as err:
        logging.error(err)
        return error(err)

    try:
        id = request.args['id']
    except KeyError:
        id = None

    yaml = yamlParser.get(name)
    titles = ['ID', '分组', '用例名称', '地址', '方法', '消息头', '参数', '状态码', '服务状态', '耗时(ms)', '返回结果']

    datas = []
    test_configs = yaml.get('test')
    dubbo = yaml.get('dubbo')
    system = yaml.get('system')
    auth = yaml.get('auth')
    for test_config in test_configs:
        if not test_config.get('system'):
            test_config['system'] = system

        if not test_config.get('auth'):
            test_config['auth'] = auth

        if id:
            if id == str(test_config.get('id')):
                if dubbo:
                    datas.append(dubbo_test(test_config))
                else:
                    datas.append(api_test(test_config))
                break
        else:
            if dubbo:
                datas.append(dubbo_test(test_config))
            else:
                datas.append(api_test(test_config))
    return tmpl(titles=titles, datas=datas)


def http_request(test):
    try:
        auth = test.get('auth')
        headers = test.get('headers')
        system = test.get('system')
        server = test.get('server')
        params = test.get('params')
        method = test.get('method')
        testApi = apiManager.get(system)
        result = testApi.request(method, server, headers=headers, params=params, auth=auth)
        return result
    except Exception as err:
        raise err


# 测试单个接口
def api_test(test):
    result_status = '<span style="color: red">fail</span>'
    status_code = -1
    times = '-'
    try:
        start = time.perf_counter()
        result = http_request(test)
        end = time.perf_counter()
        times = end - start
        status_code = result.status_code
        result_message = result.json
        if status_code == 200:
            if result.success:
                result_status = '<span style="color: green">success</span>'
    except Exception as err:
        result_message = err

    data = [test.get('id'), test.get('group'), test.get('name'), test.get('server'), test.get('method'),
            demjson.encode(test.get('headers')),
            demjson.encode(test.get('params')), status_code, result_status, times,
            demjson.encode(result_message)]

    return data


def dubbo_test(test):
    server = test.get('server')
    method = test.get('method')
    params = test.get('params')
    start = time.perf_counter()
    status, result = dubbo_invoke(server, method, params)
    end = time.perf_counter()
    times = end - start
    if status:
        result_status = '<span style="color: green">success</span>'
    else:
        result_status = '<span style="color: red">fail</span>'

    data = [test.get('id'), test.get('group'), test.get('name'), test.get('server'), test.get('method'),
            test.get('headers'),
            test.get('params'), result_status, times,
            result]
    return data


def tmpl(titles, datas, **kwargs):
    template = env.get_template('list.html')
    return template.render(titles=titles, datas=datas, **kwargs)


def error(error):
    template = env.get_template('error.html')
    return template.render(error=error)


def index(links):
    template = env.get_template('index.html')
    return template.render(links=links)


if __name__ == '__main__':
    app.run(port=5000, debug=True)
